import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTouch } from './touch';
import Taro from '@tarojs/taro';
import { tracking } from '@material/monitor';
import { rubberbandIfOutOfBounds, sleep } from './util';
import { toPX } from '../../utils';
import { getDeviceInfo } from '@material/helpers/taro';
import { useDebounce } from '@material/hooks';
export type PullLoadStatus =
    | 'idle'
    | 'loading'
    | 'loadSuccess'
    | 'loadError'
    | 'noMore'
    | 'pulling'
    | 'canRelease'
    | 'refreshing'
    | 'refreshComplete';
// 加载配置接口
export interface PullLoadProps {
    autoLoad?: boolean;
    pageSize?: number;
    historyApi?: () => Promise<[any, any[], number]>;
    disabled?: boolean;
    loadChange?: (params: { data: any[]; page: number }) => void;
    pullHeadHeight?: number;
    onRefresh?: () => Promise<any>;
    threshold?: number;
    completeDelay?: number;
    defaultPullHeight?: number;
    showPull?: boolean;
    allowRePullAfterComplete?: boolean;
}

const defaultProps = {
    autoLoad: false,
    disabled: false,
    loadDisabled: false,
    pullDisabled: false,
    pageSize: 30,
    pullHeadHeight: toPX(60),
    threshold: 60,
    completeDelay: 1000,
    defaultPullHeight: toPX(64),
    allowRePullAfterComplete: false
};
// 判断是否为加载相关状态
const isLoadStatus = (
    status: PullLoadStatus
): status is 'loading' | 'loadSuccess' | 'loadError' | 'noMore' => {
    return ['loading', 'loadSuccess', 'loadError', 'noMore'].includes(status);
};

// 判断是否为下拉相关状态
const isPullStatus = (
    status: PullLoadStatus
): status is 'pulling' | 'canRelease' | 'refreshing' | 'refreshComplete' => {
    return ['pulling', 'canRelease', 'refreshing', 'refreshComplete'].includes(status);
};

const isAndroidWeApp = getDeviceInfo().platform === 'android' && Taro.getEnv() === 'WEAPP';
export const usePullLoad = function (props: PullLoadProps) {
    const {
        autoLoad,
        disabled: globalDisabled,
        loadDisabled: propLoadDisabled,
        pullDisabled: propPullDisabled,
        historyApi,
        loadChange,
        pageSize,
        pullHeadHeight,
        threshold,
        onRefresh,
        completeDelay,
        defaultPullHeight,
        showPull,
        allowRePullAfterComplete
    } = { ...defaultProps, ...props };
    const [status, setStatus] = useState<PullLoadStatus>(autoLoad ? 'loading' : 'idle');
    const [pullHeight, setPullHeight] = useState(0);
    // 引用管理
    const pageRef = useRef(1);
    const mountedRef = useRef(true);
    const loadingLock = useRef(false);
    const isResetOpt = useRef(false);
    const pullingRef = useRef(false);
    const animationFrameRef = useRef<number | null>(null);
    const touch = useTouch();

    // 计算实际禁用状态（全局禁用优先）
    const isGloballyDisabled = useMemo(() => globalDisabled, [globalDisabled]);
    const isLoadDisabled = useMemo(
        () => isGloballyDisabled || propLoadDisabled,
        [isGloballyDisabled, propLoadDisabled]
    );
    const isPullDisabled = useMemo(
        () => isGloballyDisabled || propPullDisabled,
        [isGloballyDisabled, propPullDisabled]
    );
    const loadData = useCallback(async () => {
        // 边界条件检查：全局禁用、加载禁用或处于下拉状态时不执行
        if (
            !mountedRef.current ||
            loadingLock.current ||
            isLoadDisabled ||
            !historyApi ||
            isPullStatus(status)
        ) {
            return;
        }

        try {
            loadingLock.current = true;
            setStatus('loading');
            const [err, newData, length] = await historyApi();
            // 组件已卸载则停止
            if (!mountedRef.current) return;
            if (err) {
                loadChange?.({ data: [], page: pageRef.current });
                setStatus('loadError');
                return;
            }

            loadChange?.({ data: newData, page: pageRef.current });
            setStatus(length >= pageSize ? 'loadSuccess' : 'noMore');
            pageRef.current += 1;
        } catch (err) {
            setStatus('loadError');
        } finally {
            loadingLock.current = false;
        }
    }, [historyApi, isLoadDisabled, loadChange, pageSize, status]);

    // 滚动到底部加载更多
    const { trigger: handleScrollToLower } = useDebounce(() => {
        if (isResetOpt.current || isLoadDisabled || isPullStatus(status)) {
            isResetOpt.current = false;
            return;
        }

        // 仅在空闲或加载成功状态触发
        if (status === 'idle' || status === 'loadSuccess') {
            loadData();
            tracking('load-data', { count: pageRef.current });
        }
    }, 300);

    // 优化下拉动画计算
    const updatePullState = useCallback(
        (deltaY: number) => {
            if (animationFrameRef.current) {
                cancelAnimationFrame(animationFrameRef.current);
            }

            animationFrameRef.current = requestAnimationFrame(() => {
                const pullScrollValue = rubberbandIfOutOfBounds(
                    deltaY,
                    0,
                    0,
                    0.4,
                    30,
                    pullHeadHeight * 4
                );
                const newPullHeight = Math.max(pullScrollValue, 0);

                setPullHeight(newPullHeight);
                if (!allowRePullAfterComplete && status === 'refreshComplete') {
                    return;
                }
                // 更新下拉状态（根据高度判断）
                if (newPullHeight > threshold) {
                    if (status !== 'canRelease') setStatus('canRelease');
                } else if (status !== 'pulling') {
                    setStatus('pulling');
                }
            });
        },
        [pullHeadHeight, allowRePullAfterComplete, status, threshold]
    );

    // 触摸事件处理 - 只在非加载状态且未禁用下拉时生效
    const handleTouchStart = useCallback(
        (e: any) => {
            if (
                isPullDisabled ||
                isLoadStatus(status) ||
                (status === 'refreshComplete' && !allowRePullAfterComplete)
            ) {
                return;
            }
            touch.start(e);
        },
        [allowRePullAfterComplete, isPullDisabled, status, touch]
    );

    // 重置函数
    const resetLoad = useCallback(() => {
        if (isLoadDisabled) return;

        pageRef.current = 1;
        isResetOpt.current = true;
        loadChange?.({ data: [], page: pageRef.current });
        setStatus('idle');
    }, [isLoadDisabled, loadChange]);

    const resetPull = useCallback(() => {
        if (isPullDisabled) return;
        setPullHeight(0);
        setStatus('pulling');
    }, [isPullDisabled]);

    const reset = useCallback(() => {
        if (!isGloballyDisabled) {
            resetLoad();
            resetPull();
        }
    }, [isGloballyDisabled, resetLoad, resetPull]);
    const handleTouchMove = useCallback(
        (e: any) => {
            if (
                isPullDisabled ||
                isLoadStatus(status) ||
                (status === 'refreshComplete' && !allowRePullAfterComplete)
            ) {
                return;
            }
            touch.move(e);
            if (!touch.isVertical()) {
                return;
            }
            pullingRef.current = true;
            updatePullState(touch.touchRef.current.deltaY);
        },
        [allowRePullAfterComplete, isPullDisabled, status, touch, updatePullState]
    );
    const handleTouchEnd = useCallback(async () => {
        if (
            isPullDisabled ||
            isLoadStatus(status) ||
            (status === 'refreshComplete' && !allowRePullAfterComplete) ||
            !onRefresh
        ) {
            return;
        }

        pullingRef.current = false;

        // 处理下拉刷新逻辑
        if (status === 'canRelease') {
            setPullHeight(0);
            setStatus('refreshing');
            try {
                const isOk = await onRefresh();
                if (isOk) {
                    setStatus('refreshComplete');
                    // 新增参数判断：若不允许重复下拉，完成后不回弹到 pulling
                    if (allowRePullAfterComplete) {
                        if (completeDelay > 0) await sleep(completeDelay);
                        setStatus('pulling');
                    }
                } else {
                    setStatus('pulling');
                }
            } catch (e) {
                console.error('Refresh error:', e);
                setStatus('pulling');
            }

            setPullHeight(0);
        } else {
            // 回弹处理
            setPullHeight(0);
            setStatus('pulling');
        }
        touch.end();
    }, [isPullDisabled, status, onRefresh, touch, allowRePullAfterComplete, completeDelay]);
    // 清理函数
    useEffect(() => {
        const animationFrame = animationFrameRef.current;
        return () => {
            mountedRef.current = false;
            if (animationFrame) {
                cancelAnimationFrame(animationFrame);
            }
        };
    }, []);

    // 错误重试
    const retry = useCallback(() => {
        if (status === 'loadError' && !isLoadDisabled) {
            loadData();
            tracking('load-data-retry', { count: pageRef.current });
        }
    }, [loadData, status, isLoadDisabled]);

    // 外部更新状态（带合法性校验）
    const setExternalStatus = useCallback(
        (newStatus: PullLoadStatus) => {
            if (isGloballyDisabled) return;
            if (!showPull && isPullStatus(newStatus)) {
                console.warn('showPull is false: pull status is not allowed');
                return;
            }

            // 状态转换白名单（确保互斥性）
            const validTransitions: Record<PullLoadStatus, PullLoadStatus[]> = {
                idle: ['loading', 'pulling'],
                loading: ['loadSuccess', 'loadError', 'noMore'],
                loadSuccess: ['loading', 'pulling', 'idle'],
                loadError: ['loading', 'pulling', 'idle'],
                noMore: ['pulling', 'idle'],
                pulling: ['canRelease', 'loading', 'idle'],
                canRelease: ['refreshing', 'pulling'],
                refreshing: ['refreshComplete', 'pulling'],
                refreshComplete: ['pulling', 'loading', 'idle']
            };

            if (validTransitions[status].includes(newStatus)) {
                setStatus(newStatus);
            } else {
                console.warn(`Invalid status transition: ${status} → ${newStatus}`);
            }
        },
        [isGloballyDisabled, showPull, status]
    );

    // 计算下拉样式
    const springStyles = useMemo(() => {
        if (!showPull) return {};
        if (isPullDisabled) return {};

        const resetHeight =
            status === 'refreshComplete' || (isPullDisabled && status === 'pulling');

        const height = resetHeight ? '0px' : `${defaultPullHeight + pullHeight}px`;

        return {
            height,
            ...(!pullingRef.current || isAndroidWeApp ? { transition: 'height .3s ease-out' } : {})
        };
    }, [showPull, isPullDisabled, status, defaultPullHeight, pullHeight]);

    useEffect(() => {
        // 1. 当 showPull 从 true 变为 false（关闭下拉功能）
        if (!showPull) {
            // 若当前是下拉相关状态，强制重置为 idle
            if (isPullStatus(status)) {
                setStatus('idle');
            }
            // 重置下拉高度，避免残留UI
            setPullHeight(0);
        }
        // 2. 当 showPull 从 false 变为 true（开启下拉功能）
        else {
            // 若当前是 idle，自动切换为 pulling（下拉初始状态）
            if (status === 'idle') {
                setStatus('pulling');
            }
            if (status === 'refreshComplete' && !allowRePullAfterComplete) {
                setStatus('refreshComplete');
            }
        }
    }, [allowRePullAfterComplete, showPull, status]);

    return {
        status,
        handleScrollToLower,
        ...(showPull && {
            handleTouchStart,
            handleTouchMove,
            handleTouchEnd,
            springStyles,
            resetPull
        }),
        retry,
        setExternalStatus,
        // 暴露当前禁用状态
        isGloballyDisabled,
        isLoadDisabled,
        isPullDisabled,
        resetLoad,
        reset
    };
};
